package geometric3D;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

public class XZRectangle extends Rectangle {

	public XZRectangle() {
		super();

	}
	public XZRectangle (Point positionPoint ,int xSize, int zSize, boolean isPositiveFaced){
		this.position = positionPoint;
		this.height = zSize;
		this.width = xSize;
		this.isPositiveFaced = isPositiveFaced;
	}
	
	
	public XZRectangle(int width, int height, boolean isPositiveFaced) {
		super(width, height, isPositiveFaced);

	}
	public int getXSize(){
		return this.width;
	}
	public void setXSize(int xSize){
		this.width = xSize;
	}
	public int getZSize(){
		return this.height;
	}
	public void setZSize(int zSize){
		this.height= zSize;
	}

	
	@Override
	public String toString() {
		return "XZRectangle [position=" + position + ", width=" + width
				+ ", height=" + height + ", isPositiveFaced=" + isPositiveFaced
				+ ", getArea()=" + getArea() + "]\n";
	}
	public xLineSegment getXLineSegment(boolean isPositiveFaced){
		if(isPositiveFaced){
			return new xLineSegment(
					new Point(position.getX(), position.getY(), position.getZ()+getZSize()), 
					new Point(position.getX()+getXSize(), position.getY(), position.getZ()+getZSize()));
		}else{
			return new xLineSegment(
					new Point(position.getX(), position.getY(), position.getZ()), 
					new Point(position.getX()+getXSize(), position.getY(), position.getZ()));
		}
		
	}
	
	public zLineSegment getZLineSegment(boolean isPositiveFaced){
		if (isPositiveFaced) {
			
			return new zLineSegment(
					new Point(position.getX()+getXSize(), position.getY(), position.getZ()), 
				 	new Point(position.getX()+getXSize(), position.getY(), position.getZ()+getZSize()));
		}else{
			return new zLineSegment(
					new Point(position.getX(), position.getY(), position.getZ()), 
				 	new Point(position.getX(), position.getY(), position.getZ()+getZSize()));
		}
	}
	@Override
	public Rectangle2D toRectangle2D() {
		
		return new Rectangle2D.Double(position.getX(), position.getZ(),getXSize(),getZSize());
	}
	
	public XZRectangle getOverlaped(XZRectangle xzRectangle){
		Rectangle2D thisRectangle2D = this.toRectangle2D();
		Rectangle2D xzRectangle2D = xzRectangle.toRectangle2D();
		Rectangle2D intersection = thisRectangle2D.createIntersection(xzRectangle2D);
		Point intersectionPosition = new Point((int)intersection.getX(),position.getY(),(int)intersection.getY());
		return new XZRectangle(intersectionPosition, (int)intersection.getWidth(), (int)intersection.getHeight(), isPositiveFaced);
		
	}
	
	
	public List<XZRectangle> getLeftOver(XZRectangle xzRectangle, Rectangle2DRelation relation){
		List<XZRectangle> result = new ArrayList<XZRectangle>();
		if(relation ==  Rectangle2DRelation.OUTSIDE
				|| relation ==  Rectangle2DRelation.TOUCHING){
			result.add(this);
		}else if(relation ==  Rectangle2DRelation.INSIDE){
		}else if(relation ==  Rectangle2DRelation.CONTAIN){
			result.addAll(getLeftOverInside(xzRectangle));
		}else if(relation == Rectangle2DRelation.ONEINSIDE){
			result.addAll(getLeftOverOnePoint(xzRectangle));
		}else if(relation == Rectangle2DRelation.TWOINSIDE){
			result.addAll(getLeftOverTwoPoint(xzRectangle));
		}else if(relation == Rectangle2DRelation.ZEROINSIDE){
			result.addAll(getLeftOverZeroPoint(xzRectangle));
		}
		return result;
		
	}
	
	public int getMaxX(){
		return this.position.getX() + this.getXSize();
	}
	
	public int getMinX(){
		return this.position.getX();
	}
	public int getMaxZ(){
		return this.position.getZ()+this.getZSize();
	}
	public int getMinZ(){
		return this.position.getZ();
	}
	

	
	public List<XZRectangle> getLeftOverInside(XZRectangle xzRectangle) {
		List<XZRectangle> result = new ArrayList<XZRectangle>();
		
		int leftOverX =-1;
		int leftOverZ =-1;
		int leftOverPositionX =-1;
		int leftOverPositionZ =-1;
		
		leftOverX = xzRectangle.getMinX() - this.getMinX();
		leftOverZ = this.getZSize();
		leftOverPositionX = this.getMinX();
		leftOverPositionZ = this.getMinZ();
		
		if(leftOverX>0 && leftOverZ>0){
			result.add(new XZRectangle(new Point(leftOverPositionX,this.position.getY(),leftOverPositionZ),
					leftOverX, leftOverZ, this.isPositiveFaced));
			
		}
		
		leftOverX = xzRectangle.getXSize();
		leftOverZ = xzRectangle.getMinZ() - this.getMinZ();
		leftOverPositionX = xzRectangle.getMinX();
		leftOverPositionZ = this.getMinZ();
		
		if(leftOverX>0 && leftOverZ>0){
			result.add(new XZRectangle(new Point(leftOverPositionX,this.position.getY(),leftOverPositionZ),
					leftOverX, leftOverZ, this.isPositiveFaced));
			
		}
		
		leftOverX = xzRectangle.getXSize();
		leftOverZ = this.getMaxZ() - xzRectangle.getMaxZ();
		leftOverPositionX = xzRectangle.getMinX();
		leftOverPositionZ = xzRectangle.getMaxZ();
		
		if(leftOverX>0 && leftOverZ>0){
			result.add(new XZRectangle(new Point(leftOverPositionX,this.position.getY(),leftOverPositionZ),
					leftOverX, leftOverZ, this.isPositiveFaced));
			
		}
		
		leftOverX = this.getMaxX() - xzRectangle.getMaxX();
		leftOverZ = this.getZSize();
		leftOverPositionX = xzRectangle.getMaxX();
		leftOverPositionZ = this.getMinZ();
		
		if(leftOverX>0 && leftOverZ>0){
			result.add(new XZRectangle(new Point(leftOverPositionX,this.position.getY(),leftOverPositionZ),
					leftOverX, leftOverZ, this.isPositiveFaced));
			
		}
		
		
		
		
		return result;
		
	}
	
//	public Rectangle2DRelation findRelation(XZRectangle xzRectangle){
//		Rectangle2D this2D = this.toRectangle2D();
//		Rectangle2D xyRectangle2D = xzRectangle.toRectangle2D();
//		
//		if(xyRectangle2D.contains(this2D))return Rectangle2DRelation.INSIDE;
//		if(this2D.contains(xyRectangle2D)) return Rectangle2DRelation.CONTAIN;
//		if((this.getMinX() == xzRectangle.getMaxX()
//				|| this.getMaxX() == xzRectangle.getMinX())
//				&& (xzRectangle.getMinZ() <= this.getMaxZ()  
//						&& xzRectangle.getMinZ() >= this.getMinZ() 
//					||xzRectangle.getMaxZ() <= this.getMaxZ()  
//						&& xzRectangle.getMaxZ() >= this.getMinZ())){
//			return Rectangle2DRelation.TOUCHING;
//		}else if((this.getMinZ() == xzRectangle.getMaxZ()
//				|| this.getMaxZ() == xzRectangle.getMinZ())
//				&& ((xzRectangle.getMinX() <= this.getMaxX()  
//						&& xzRectangle.getMinX() >= this.getMinX()) 
//					||(xzRectangle.getMaxX() <= this.getMaxX()  
//						&& xzRectangle.getMaxX() >= this.getMinX()))){
//			return Rectangle2DRelation.TOUCHING;
//		}else if(this2D.intersects(xyRectangle2D)){
//			int pointContain =0 ;
////			System.out.println(this.getPoint2D());
////			System.out.println(xyRectangle.getPoint2D());
//			for(Point2D p2D : xzRectangle.getPoint2D()){
//				if(this2D.contains(p2D)){
////					System.out.println(p2D);
//					pointContain++;
//				}
//				
//			}
//			if(pointContain==0){
//				return Rectangle2DRelation.ZEROINSIDE;
//			}else if(pointContain==1){
//				return Rectangle2DRelation.ONEINSIDE;
//			}else if(pointContain==2){
//				return Rectangle2DRelation.TWOINSIDE;
//			}
//			
//		}
//		return Rectangle2DRelation.OUTSIDE;
//		
//	}
	public List<Point2D> getPoint2D() {
		List<Point2D> result = new ArrayList<Point2D>();
		result.add(new Point2D.Double(getMinX(), getMinZ()));
		result.add(new Point2D.Double(getMaxX(), getMinZ()));
		result.add(new Point2D.Double(getMaxX(), getMaxZ()));
		result.add(new Point2D.Double(getMinX(), getMaxZ()));
		
		
		return result;
	} 
	
	public  List<XZRectangle> getLeftOverOnePoint(XZRectangle xzRectangle){
		List<XZRectangle> result = new ArrayList<XZRectangle>();
		Rectangle2D thisRectangle2D = this.toRectangle2D();
//		Rectangle2D xzRectangle2D = this.toRectangle2D();
		Rectangle2D intersection = this.getOverlaped(xzRectangle).toRectangle2D();
		int leftOver1X  = (int)(thisRectangle2D.getWidth()  - intersection.getWidth());
		int leftOver1Z  = (int)(thisRectangle2D.getHeight());
		
		int leftOver2X  = (int)(intersection.getWidth());
		int leftOver2Z  = (int)(thisRectangle2D.getHeight() - intersection.getHeight());
		
		int leftOver1PositionX =-1;
		int leftOver1PositionZ =-1;
		int leftOver1PositionY =this.position.getY();
		int leftOver2PositionX =-1;
		int leftOver2PositionZ =-1;
		int leftOver2PositionY =this.position.getY();
		
		if(thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.TOPLEFT))){
			leftOver1PositionX = this.getMinX();
			leftOver1PositionZ = this.getMinZ();
			
			leftOver2PositionX = xzRectangle.getMinX();
			leftOver2PositionZ = xzRectangle.getMaxZ();
			
			
		}else if(thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.TOPRIGHT))){
			leftOver1PositionX = xzRectangle.getMaxX();
			leftOver1PositionZ = this.getMinZ();
			
			leftOver2PositionX = this.getMinX();
			leftOver2PositionZ = xzRectangle.getMaxZ();
		}else if(thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.BOTTOMLEFT))){
			leftOver1PositionX = this.getMinX();
			leftOver1PositionZ = this.getMinZ();
			
			leftOver2PositionX = xzRectangle.getMinX();
			leftOver2PositionZ = this.getMinZ();
		}else if(thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.BOTTOMRIGHT))){
			leftOver1PositionX = xzRectangle.getMaxX();
			leftOver1PositionZ = this.getMinZ();
			
			leftOver2PositionX = this.getMinX();
			leftOver2PositionZ = this.getMinZ();
		}
		
		if(leftOver1X >0 && leftOver1Z >0 ){
			Point position = new Point(leftOver1PositionX,leftOver1PositionY, leftOver1PositionZ );
			result.add(new XZRectangle(position,leftOver1X,leftOver1Z,this.isPositiveFaced));
		}
		if(leftOver2X >0 && leftOver2Z >0 ){
			Point position = new Point(leftOver2PositionX, leftOver2PositionY, leftOver2PositionZ);
			result.add(new XZRectangle(position,leftOver2X,leftOver2Z,this.isPositiveFaced));
		}
		
		
		
		return result;
		
		
	}
	
	public Point2D  getPoint2D (RectanglePoint e){
//		System.out.println(this.centerPoint.z()-this.zSize/2);
		if(e==RectanglePoint.TOPLEFT){
			return new Point2D.Double(getMinX(), getMaxZ());
		}else if (e== RectanglePoint.TOPRIGHT){
			return new Point2D.Double(getMaxX(), getMaxZ());
		}else if(e==RectanglePoint.BOTTOMLEFT){
			return new Point2D.Double(getMinX(), getMinZ());
		}else if (e== RectanglePoint.BOTTOMRIGHT){
			return new Point2D.Double(getMaxX(), getMinZ());
		} 

		return null;
		
	}
	public List<XZRectangle> getLeftOverZeroPoint(XZRectangle xzRectangle){
		List<XZRectangle> result = new ArrayList<XZRectangle>();
//		Rectangle2D thisRectangle2D = this.toRectangle2D();
		Rectangle2D xzRectangle2D = xzRectangle.toRectangle2D();
		int leftOver1X = -1;
		int leftOver1Z = -1;
		int leftOverPosition1X = -1;
		int leftOverPosition1Z = -1;
		
		int leftOver2X = -1;
		int leftOver2Z = -1;
		int leftOverPosition2X = -1;
		int leftOverPosition2Z = -1;
		
		
		
		if((xzRectangle2D.contains(this.getPoint2D(RectanglePoint.TOPLEFT)) &&
				xzRectangle2D.contains(this.getPoint2D(RectanglePoint.TOPRIGHT)) )
				||(xzRectangle2D.contains(this.getPoint2D(RectanglePoint.BOTTOMLEFT)) &&
						xzRectangle2D.contains(this.getPoint2D(RectanglePoint.BOTTOMRIGHT)))){
			leftOver1X = this.getXSize();
			leftOverPosition1X = this.getMinX();
			if(xzRectangle2D.contains(this.getPoint2D(RectanglePoint.TOPLEFT)) &&
					xzRectangle2D.contains(this.getPoint2D(RectanglePoint.TOPRIGHT))){
				leftOver1Z = xzRectangle.getMinZ()-this.getMinZ();
				leftOverPosition1Z = this.getMinZ();
				
			}else{
				leftOver1Z = this.getMaxZ() - xzRectangle.getMaxZ();
				leftOverPosition1Z =xzRectangle.getMaxZ();
			}
		}else if((xzRectangle2D.contains(this.getPoint2D(RectanglePoint.TOPLEFT)) &&
				xzRectangle2D.contains(this.getPoint2D(RectanglePoint.BOTTOMLEFT)) )
				||(xzRectangle2D.contains(this.getPoint2D(RectanglePoint.TOPRIGHT)) &&
						xzRectangle2D.contains(this.getPoint2D(RectanglePoint.BOTTOMRIGHT)))){
			leftOver1Z = this.getZSize();
			leftOverPosition1Z = this.getMinZ();
			if(xzRectangle2D.contains(this.getPoint2D(RectanglePoint.TOPLEFT)) &&
					xzRectangle2D.contains(this.getPoint2D(RectanglePoint.BOTTOMLEFT))){
				leftOver1X = this.getMaxX()- xzRectangle.getMaxX();
				leftOverPosition1X = xzRectangle.getMaxX();
				
			}else{
				leftOver1X = xzRectangle.getMinX() - this.getMinX();
				leftOverPosition1X = this.getMinX();
			}
		}else if(this.getMaxZ() > xzRectangle.getMaxZ()){
			leftOver1X = this.getXSize();
			leftOver1Z = xzRectangle.getMinZ() - this.getMinZ();
			leftOverPosition1X  = this.getMinX();
			leftOverPosition1Z  = this.getMinZ();
			
			leftOver2X = this.getXSize();
			leftOver2Z = this.getMaxZ() - xzRectangle.getMaxZ();
			leftOverPosition2X = this.getMinX();
			leftOverPosition2Z = xzRectangle.getMaxZ();
			
		}else{
			leftOver1X = xzRectangle.getMinX() - this.getMinX();
			leftOver1Z = this.getZSize();
			leftOverPosition1X  = this.getMinX();
			leftOverPosition1Z  = this.getMinZ();
			
			leftOver2X = this.getMaxX() - xzRectangle.getMaxX();
			leftOver2Z = this.getZSize();
			leftOverPosition2X = xzRectangle.getMaxX();
			leftOverPosition2Z = this.getMinZ();
		}
		
		if(leftOver1X>0 && leftOver1Z>0){
			result.add(new XZRectangle(new Point(leftOverPosition1X,this.position.getY(),leftOverPosition1Z),
					leftOver1X,leftOver1Z, this.isPositiveFaced ));
			
		}
		
		if(leftOver2X>0 && leftOver2Z>0){
			result.add(new XZRectangle(new Point(leftOverPosition2X,  this.position.getY(),leftOverPosition2Z),
					leftOver2X,leftOver2Z, this.isPositiveFaced ));
			
		}
		
		
		return result;
	}
	
	public List<XZRectangle> getLeftOverTwoPoint(XZRectangle xzRectangle){
		List<XZRectangle> result = new ArrayList<XZRectangle>();
		Rectangle2D thisRectangle2D = this.toRectangle2D();
//		Rectangle2D xzRectangle2D = this.toRectangle2D();
		int leftOver1X = -1;
		int leftOver1Z = -1;
		
		int leftOver2X = -1;
		int leftOver2Z = -1;
		int leftOver2PositionX =-1;
		int leftOver2PositionZ =-1;
		int leftOver2PositionY =this.position.getY();
		
		int leftOver3X = -1;
		int leftOver3Z = -1;
		int leftOver3PositionX =-1;
		int leftOver3PositionZ =-1;
		int leftOver3PositionY =this.position.getY();
		
		Point leftOver1Position = this.position;
		if((thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.TOPLEFT)) && 
				thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.TOPRIGHT)))
				||  (thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.BOTTOMLEFT)) && 
						thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.BOTTOMRIGHT)))){
			leftOver1X = xzRectangle.getMinX() - this.getMinX();
			leftOver1Z = this.getZSize();
			
			leftOver2X = xzRectangle.getXSize();
			leftOver2PositionX = xzRectangle.getMinX();
			
			leftOver3X = this.getMaxX() - xzRectangle.getMaxX();
			leftOver3Z = this.getZSize();
			leftOver3PositionX = xzRectangle.getMaxX();
			
			if((thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.TOPLEFT)) && 
					thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.TOPRIGHT)))){
				leftOver2Z = this.getMaxZ() - xzRectangle.getMaxZ();
				leftOver2PositionZ = xzRectangle.getMaxZ();
				leftOver3PositionZ = this.getMinZ();
			}else{
				leftOver2Z = xzRectangle.getMinZ() - this.getMinZ();
				leftOver2PositionZ = this.getMinZ();
				leftOver3PositionZ = this.getMinZ();
			}
			
			
		}else if((thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.TOPLEFT)) && 
				thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.BOTTOMLEFT))
				||(thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.TOPRIGHT)) && 
						thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.BOTTOMRIGHT))))){
			
			leftOver1X = this.getXSize();
			leftOver1Z = xzRectangle.getMinZ()- this.getMinZ();
			
			leftOver2Z = xzRectangle.getZSize();
			leftOver2PositionZ = xzRectangle.getMinZ();

			leftOver3X = this.getXSize();
			leftOver3Z = this.getMaxZ() -  xzRectangle.getMaxZ();
			leftOver3PositionX = this.getMinX();
			leftOver3PositionZ = xzRectangle.getMaxZ();
			
			if((thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.TOPLEFT)) && 
					thisRectangle2D.contains(xzRectangle.getPoint2D(RectanglePoint.BOTTOMLEFT)))){
				leftOver2PositionX = this.getMinX();
				leftOver2X =  xzRectangle.getMinX() - this.getMinX();
				
			}else{
				leftOver2PositionX = xzRectangle.getMaxX();
				leftOver2X =  this.getMinX()-xzRectangle.getMinX() ;
			}
			
		
		
		}
		
		if(leftOver1X >0  && leftOver1Z >0){
			
			result.add(new XZRectangle(leftOver1Position, leftOver1X, leftOver1Z, this.isPositiveFaced));
			
		}
		
		if(leftOver2X >0  && leftOver2Z >0){
			Point position = new Point(leftOver2PositionX,  leftOver2PositionY,leftOver2PositionZ);
			result.add(new XZRectangle(position, leftOver2X, leftOver2Z, this.isPositiveFaced));
			
		}
		
		if(leftOver3X >0  && leftOver3Z >0){
			Point position = new Point(leftOver3PositionX, leftOver3PositionY,leftOver3PositionZ);
			result.add(new XZRectangle(position, leftOver3X, leftOver3Z, this.isPositiveFaced));
			
		}
		return result;
	}
	
	public XZRectangle reverse(){
		this.isPositiveFaced = !this.isPositiveFaced;
		return this;
	}
	
}
